﻿using System;
using System.Deployment.Application;
using System.Diagnostics;
using System.Text;
using System.Windows;
using IronCow;
using Milkify.Interfaces;
using Milkify.Data;
using Milkify.Input;
using System.Reflection;

namespace Milkify.Controllers
{
    public class AboutController : Controller
    {
        private IView mView;

        public AboutController(ControllerContext context, Rtm rtm, IViewContainer viewContainer, IViewFactory viewFactory)
            : base(context, rtm, viewContainer)
        {
            mView = viewFactory.Create("About");
        }

        public override void Execute()
        {
            string applicationVersion;
            if (ApplicationDeployment.IsNetworkDeployed)
            {
                applicationVersion = string.Format("{0} (installed from network)", ApplicationDeployment.CurrentDeployment.CurrentVersion.ToString());
            }
            else
            {
                var mainAssembly = Assembly.GetEntryAssembly();
                var mainAssemblyName = new AssemblyName(mainAssembly.FullName);
                if (!string.IsNullOrEmpty(mainAssemblyName.Version.ToString()))
                {
                    applicationVersion = string.Format("{0} (not installed)", mainAssemblyName.Version);
                }
                else
                {
                    applicationVersion = string.Format("Unknown version (not installed)");
                }
            }

            // Build the view data.
            var viewData = new AboutViewData();
            viewData.ApplicationVersion = applicationVersion;
            viewData.CheckForUpdatesCommand = new DecoupledCommand(CheckForUpdates, CanCheckForUpdates);
            viewData.NavigateToCreditsCommand = new DecoupledCommand(NavigateToCredits);
            mView.ViewData = viewData;

            // Change the current view.
            ViewContainer.NavigateToView(mView);
        }

        private void NavigateToCredits()
        {
            System.Diagnostics.Process.Start("http://www.milkify.com/credits");
        }

        private bool CanCheckForUpdates()
        {
            return ApplicationDeployment.IsNetworkDeployed;
        }

        private void CheckForUpdates()
        {
            UpdateCheckInfo info = null;

            if (ApplicationDeployment.IsNetworkDeployed)
            {
                ApplicationDeployment ad = ApplicationDeployment.CurrentDeployment;

                try
                {
                    info = ad.CheckForDetailedUpdate();
                }
                catch (DeploymentDownloadException dde)
                {
                    throw new ApplicationException(
                        "The new version of the application cannot be downloaded at this time.\n\n" +
                        "Please check your network connection, or try again later.",
                        dde);
                }
                catch (InvalidDeploymentException ide)
                {
                    throw new ApplicationException(
                        "Cannot check for a new version of the application. The ClickOnce deployment is corrupt. " +
                        "Please redeploy the application and try again.",
                        ide);
                }
                catch (InvalidOperationException ioe)
                {
                    throw new ApplicationException(
                        "This application cannot be updated. It is likely not a ClickOnce application.",
                        ioe);
                }

                if (info.UpdateAvailable)
                {
                    Boolean doUpdate = true;

                    if (!info.IsUpdateRequired)
                    {
                        MessageBoxResult dr = MessageBox.Show(
                            "An update is available. Would you like to update the application now?",
                            "Update Available",
                            MessageBoxButton.OKCancel);
                        if (!(MessageBoxResult.OK == dr))
                        {
                            doUpdate = false;
                        }
                    }
                    else
                    {
                        // Display a message that the app MUST reboot. Display the minimum required version.
                        MessageBox.Show(
                            "This application has detected a mandatory update from your current " +
                            "version to version " + info.MinimumRequiredVersion.ToString() +
                            ". The application will now install the update and restart.",
                            "Update Available",
                            MessageBoxButton.OK,
                            MessageBoxImage.Information);
                    }

                    if (doUpdate)
                    {
                        try
                        {
                            ad.Update();
                            MessageBox.Show("The application has been upgraded, and will now restart.");
                            RestartApplication();
                        }
                        catch (DeploymentDownloadException dde)
                        {
                            throw new ApplicationException(
                                "Cannot install the latest version of the application. \n\n" +
                                "Please check your network connection, or try again later.",
                                dde);
                        }
                    }
                }
                else
                {
                    MessageBox.Show(
                        "You are running the latest available version. Yay!",
                        "No Updates Available",
                        MessageBoxButton.OK,
                        MessageBoxImage.Information);
                }
            }
        }

        private void RestartApplication()
        {
            Application.Current.Exit += new ExitEventHandler(CurrentApplication_Exit);
            Application.Current.Shutdown();
        }

        private void CurrentApplication_Exit(object sender, ExitEventArgs e)
        {
            string[] commandLineArgs = Environment.GetCommandLineArgs();
            StringBuilder builder = new StringBuilder((commandLineArgs.Length - 1) * 16);
            for (int i = 1; i < (commandLineArgs.Length - 1); i++)
            {
                builder.Append('"');
                builder.Append(commandLineArgs[i]);
                builder.Append("\" ");
            }
            if (commandLineArgs.Length > 1)
            {
                builder.Append('"');
                builder.Append(commandLineArgs[commandLineArgs.Length - 1]);
                builder.Append('"');
            }

            Process currentProcess = Process.GetCurrentProcess();
            ProcessStartInfo startInfo = currentProcess.StartInfo;
            startInfo.FileName = currentProcess.StartInfo.FileName;
            if (builder.Length > 0)
            {
                startInfo.Arguments = builder.ToString();
            }

            Process.Start(startInfo);
        }
    }
}
